package api;

import interfaces.Notificador;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import api.ControlReflection.Metodo;

public class Regla {
	
	Respuesta respuesta;
	ArrayList<ObjetoAfectado> listaObjetos;
	private boolean activa = true;
	private String importancia;
	
	/**
	 * @return the importancia
	 */
	public String getImportancia() {
		return importancia;
	}

	/**
	 * @param importancia the importancia to set
	 */
	public void setImportancia(String importancia) {
		this.importancia = importancia;
	}

	public Regla(){
		listaObjetos = new ArrayList<ObjetoAfectado>();
	}
	
	public Regla(Respuesta r){
		respuesta = r;
		listaObjetos = new ArrayList<ObjetoAfectado>();
	}
	
	public Regla(Respuesta respuesta,ArrayList<ObjetoAfectado> objetosAfectados){
		this.respuesta = respuesta;
		this.listaObjetos = objetosAfectados;
	}
	
	public void agregarObjeto(String id, Notificador objeto, Metodo metodo){
		ObjetoAfectado od= new ObjetoAfectado(id, objeto,  metodo);
		listaObjetos.add(od);
	}
	
	public void quitarObjeto(String id, Notificador objeto, Metodo metodo){
		ObjetoAfectado od= new ObjetoAfectado(id, objeto, metodo);
		listaObjetos.remove(od);
	}
	
	public int cantObjetos(){
		return listaObjetos.size();
	}
	
	public List<Metodo> obtenerMetodos(Notificador obj){
		Iterator<ObjetoAfectado> it = listaObjetos.iterator();
		List<Metodo> lista = new ArrayList<Metodo>();
		
		while(it.hasNext()){
			ObjetoAfectado compara = (ObjetoAfectado) it.next();
			if (compara.getObjeto().getClass().equals(obj.getClass())){
				if (compara.getObjeto().equals(obj)) {
					lista.add(compara.getMetodo());
				}
			}
		}
		return lista;
	}
	
	public String getDescripcion(){
		return this.respuesta.getDescripcion();
	}
	
	public String toString(){
		return this.getDescripcion();
	}
	
	public Respuesta getRespuesta(){
		return this.respuesta;
	}
	
	public boolean equals(Object obj){	
		boolean salida = false;      
        if (obj != null && (obj.getClass().equals(this.getClass()))) {
           Regla regla = (Regla)obj;           
           salida  = (this.getRespuesta().equals(regla.getRespuesta()));
           
           Iterator itObjetos =this.getObjetosAfectados().iterator();
           Iterator itObjetosCompara = regla.getObjetosAfectados().iterator();
           while (itObjetos.hasNext() && salida){
        	   salida = regla.getObjetosAfectados().contains(itObjetos.next());
        	   /*
        	   ObjetoAfectado oa = (ObjetoAfectado) itObjetos.next();
        	   while (itObjetosCompara.hasNext() && salida){
        		   salida = oa.equals(itObjetosCompara.next());
        	   } 
        	   */   	   
           }       
       }
       return salida;
	}
	
	
	public List<ObjetoAfectado> getObjetosAfectados(){
		return this.listaObjetos;
	}
	
	public class ObjetoAfectado {
		String id;
		Metodo metodo;
		Notificador objeto;
		
		public Metodo getMetodo() {
			return this.metodo;
		}

		public void setMetodo(Metodo metodo) {
			this.metodo = metodo;
		}

		public Notificador getObjeto() {
			return this.objeto;
		}
		
		public String getId(){
			return this.id;
		}

		public void setObjeto(Notificador objeto) {
			this.objeto = objeto;
		}

		public ObjetoAfectado (String id, Notificador obj, Metodo met) {
			this.id = id;
			this.objeto = obj;
			this.metodo = met;
		}
		public String toString(){
			return this.id + " - " + metodo.toString();
		}

		public boolean equals(Object obj){	
			boolean salida = false;      
	        if (obj != null && (obj.getClass().equals(this.getClass()))) {
	           ObjetoAfectado od= (ObjetoAfectado)obj;           
	           salida  = (this.objeto.equals(od.getObjeto())
	        		   		&& this.metodo.equals(od.getMetodo())
	        		   		&& this.id.compareTo(od.getId()) == 0);
	       }
	       return salida;
		}
	}
	
	public boolean verificarRegla(){
		return this.respuesta.controlarNecesarios();
	}
	
	public void ejecutar(){
		if (this.activa){
			ControlReflection cr = new ControlReflection();
			Iterator<ObjetoAfectado> it = listaObjetos.iterator();
			
			while(it.hasNext()){
				ObjetoAfectado objetoAfectado = (ObjetoAfectado) it.next();
				Notificador notificador = objetoAfectado.getObjeto();
				Metodo metodo = objetoAfectado.getMetodo();
				cr.ejecutar(notificador, metodo);
			}
		}
	}
	
	public void setActivada(boolean estado){
		this.activa = estado;
	}
		
	public boolean isActiva(){
		return this.activa;
	}
	
}
